package com.heu.blood.recycle.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heu.blood.bloodtest.service.BloodSampleService;
import com.heu.blood.common.Constant.ConstantData;
import com.heu.blood.common.enums.OperateStateEnum;
import com.heu.blood.common.utils.GenerateNumberBySnowFlake;
import com.heu.blood.common.utils.PageUtils;
import com.heu.blood.common.utils.Query;
import com.heu.blood.examine.dictenum.TradeTypeEnum;
import com.heu.blood.examine.entity.OperateExamineEntity;
import com.heu.blood.examine.service.OperateExamineService;
import com.heu.blood.globalExceptionHandler.MyException;
import com.heu.blood.match.dao.BloodMatchDao;
import com.heu.blood.match.dao.PatientInformationDao;
import com.heu.blood.match.entity.BloodMatchEntity;
import com.heu.blood.match.entity.PatientInformationEntity;
import com.heu.blood.match.service.BloodInformationService;
import com.heu.blood.match.service.BloodMatchService;
import com.heu.blood.recycle.dao.BloodReturnDao;
import com.heu.blood.recycle.dictenum.BloodReturnVerifyStateEnum;
import com.heu.blood.recycle.entity.BloodReturnEntity;
import com.heu.blood.recycle.exception.BloodReturnException;
import com.heu.blood.recycle.service.BloodReturnService;
import com.heu.blood.recycle.service.BloodTrackService;
import com.heu.blood.recycle.vo.BloodReturnApplicationVo;
import com.heu.blood.recycle.vo.BloodReturnEntityVo;
import com.heu.blood.recycle.vo.BloodReturnWithExamineVo;
import com.heu.blood.security.entity.LoginUser;
import com.heu.blood.send.dao.BloodSendDao;
import com.heu.blood.send.entity.BloodSendEntity;
import com.heu.blood.send.service.BloodSendService;
import com.heu.blood.storge.entity.BloodInStorgeEntity;
import com.heu.blood.storge.service.BloodInStorgeService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;


@Service
public class BloodReturnServiceImpl extends ServiceImpl<BloodReturnDao, BloodReturnEntity> implements BloodReturnService {

    @Autowired
    private BloodReturnDao bloodReturnDao;
    @Autowired
    private BloodSampleService bloodSampleService;
    @Autowired
    private BloodMatchService bloodMatchService;
    @Autowired
    private BloodTrackService bloodTrackService;
    @Autowired
    private BloodInformationService bloodInformationService;
    @Autowired
    private BloodInStorgeService bloodInStorgeService;
    @Autowired
    private OperateExamineService operateExamineService;

    @Autowired
    private BloodMatchDao bloodMatchDao;

    @Autowired
    private BloodSendDao bloodSendDao;

    @Autowired
    private BloodSendService bloodSendService;

    @Autowired
    private PatientInformationDao patientInformationDao;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {

        //检索条件获取
        BloodReturnEntityVo bloodReturnEntityVo = new BloodReturnEntityVo();
        if(Strings.isNotBlank((String)params.get("patientName")))
            bloodReturnEntityVo.setPatientName((String)params.get("patientName"));
        if(Strings.isNotBlank((String)params.get("patientId")))
            bloodReturnEntityVo.setPatientId((String)params.get("patientId"));
        if(Strings.isNotBlank((String)params.get("bloodId")))
            bloodReturnEntityVo.setBloodId((String)params.get("bloodId"));
        if(Strings.isNotBlank((String)params.get("review")))
            bloodReturnEntityVo.setReview((String)params.get("review"));
        //添加时间范围条件
        String startTime = null;
        String endTime = null;
        if(Strings.isNotBlank((String)params.get("startTime")))
            startTime = (String)params.get("startTime");
        if(Strings.isNotBlank((String)params.get("endTime")))
            endTime = (String)params.get("endTime");

        //构建构造器
        QueryWrapper<BloodReturnEntityVo> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("patient_name",bloodReturnEntityVo.getPatientName());
        queryWrapper.like(Strings.isNotBlank(bloodReturnEntityVo.getPatientId()),"patient_id",bloodReturnEntityVo.getPatientId())
                .like(Strings.isNotBlank(bloodReturnEntityVo.getPatientName()),"patient_name",bloodReturnEntityVo.getPatientName())
                .like(Strings.isNotBlank(bloodReturnEntityVo.getBloodId()),"r.blood_id",bloodReturnEntityVo.getBloodId())
                .eq(Strings.isNotBlank(bloodReturnEntityVo.getReview()),"review",bloodReturnEntityVo.getReview())
                .ge(Strings.isNotBlank(startTime), "dispatch_time",startTime)
                .le(Strings.isNotBlank(endTime),"dispatch_time",endTime)
                .eq("r.if_show",1);

        //IPage分页查询
        IPage<BloodReturnEntityVo> page = bloodReturnDao.selectBloodReturn(
                new Query<BloodReturnEntityVo>().getPage(params),
                queryWrapper);

        return new PageUtils(page);
    }

    /**
     * 根据唯一标识id查询退血信息
     * @param id
     * @return BloodReturnEntityVo
     */
    @Override
    public BloodReturnEntityVo getById(Long id) {

        return bloodReturnDao.selectById(id);
    }

    /**
     * 添加一条退血记录
     * @param bloodReturnEntity
     * @return
     */
    @Override
    @Transactional
    public Boolean saveBloodReturn(BloodReturnWithExamineVo bloodReturnEntity) {

        //获取配血时间
//        if(bloodReturnEntity.getMatchTime() == null){
//            BloodMatchEntity bloodMatchEntity = new BloodMatchEntity();
//            bloodMatchEntity.setBloodId(bloodReturnEntity.getBloodId());
//            List<BloodMatchEntity> bloodMatchEntities = bloodMatchService.query(bloodMatchEntity);
//            //选择配血成功的配血记录
//            for(int i = 0;i < bloodMatchEntities.size();i++){
//                if(bloodMatchEntities.get(i).getState() == "BLOOD_MATCH_COMPLETED")
//                    bloodReturnEntity.setMatchTime(bloodMatchEntities.get(i).getMatchTime());
//            }
//        }

        //通过bloodId获取bloodSampleId
//        if (bloodReturnEntity.getBloodSampleId() == null){
//            BloodSampleEntity bloodSample = bloodSampleService.getByBloodId(bloodReturnEntity.getBloodId());
//            if(bloodSample != null){
//                bloodReturnEntity.setBloodSampleId(bloodSample.getBloodSampleId());
//            }
//        }

        //获取发血时间
//        if(bloodReturnEntity.getDispatchTime() == null){
//            BloodTrackEntity bloodTrack = bloodTrackService.queryByBloodId(bloodReturnEntity.getBloodId());
//            if(bloodTrack != null){
//                bloodReturnEntity.setDispatchTime(bloodTrack.getDispatchTime());
//            }
//        }
        //退血申请状态
//        bloodReturnEntity.setReview("PATIENT_BLOOD_RETURN_UNREVIEWED");
        //更新血液状态
//        boolean bloodUpdate = bloodInformationService.updateBloodStateByBloodId(bloodReturnEntity.getBloodId(),"PATIENT_BLOOD_RETURN_UNREVIEWED");
        //更新库存表
//        boolean storgeUpdate = bloodInStorgeService.updateInStorgeBloodStatebyBloodId(bloodReturnEntity.getBloodId(),"PATIENT_BLOOD_RETURN_UNREVIEWED");

//        OperateExamineEntity operateExamineEntity = new OperateExamineEntity();
//        operateExamineEntity.setOperateState(OperateStateEnum.WAIT.code());
//        operateExamineEntity.setTradeType(TradeTypeEnum.BLOOD_RETURN.code());
//        operateExamineEntity.setOperatorName();

        // 1. 用 bloodId 查询 blood_send 表
        String bloodId = bloodReturnEntity.getBloodId();
        LambdaQueryWrapper<BloodSendEntity> bloodSendQuery = new LambdaQueryWrapper<>();
        bloodSendQuery.eq(BloodSendEntity::getBloodId,bloodId);
        BloodSendEntity bloodSend = bloodSendDao.selectOne(bloodSendQuery);

        if (bloodSend == null) {
            throw new MyException(BloodReturnException.NO_SEND_RECORD);
        }
        LambdaQueryWrapper<BloodReturnEntity> bloodReturnQuery = new LambdaQueryWrapper<>();
        bloodReturnQuery.eq(BloodReturnEntity::getBloodId,bloodId);
        BloodReturnEntity bloodReturn = bloodReturnDao.selectOne(bloodReturnQuery);
        if (bloodReturn != null){
            throw  new MyException(BloodReturnException.DUPLICATE_RETURN);
        }


        // 2. 获取发血时间（operatorTime 字段）
        Date sendTime = bloodSend.getOperatorTime();

        // 3. 判断是否超过30分钟
        long now = System.currentTimeMillis();
        long send = sendTime.getTime();
        long diffMinutes = (now - send) / (60 * 1000);
        if (diffMinutes > 30) {
            throw new MyException(BloodReturnException.TIME_OUT);
        }


        // 在这里需要给这个Entity塞进去一个Id，该Id代表唯一标识
//        GenerateNumberBySnowFlake generateNumberBySnowFlake = new GenerateNumberBySnowFlake(ConstantData.APPLICATION_NO_WORK_ID, ConstantData.APPLICATION_NO_PREFIX);
//        String bloodReturnId = generateNumberBySnowFlake.genNumberByflag();


        String returnPrefix = ConstantData.BLOOD_RETURN_NO_WORK_ID; // 例如 "BR"
        String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());

        QueryWrapper<BloodReturnEntity> returnWrapper = new QueryWrapper<>();
        returnWrapper.likeRight("blood_return_id", returnPrefix + dateStr);
        returnWrapper.orderByDesc("blood_return_id");
        returnWrapper.last("limit 1");
        BloodReturnEntity maxReturnEntity = bloodReturnDao.selectOne(returnWrapper);

        int nextReturnSeq = 1;
        if (maxReturnEntity != null && maxReturnEntity.getBloodReturnId() != null) {
            String maxNo = maxReturnEntity.getBloodReturnId();
            if (maxNo.length() >= (returnPrefix.length() + 8 + 4)) {
                String seqStr = maxNo.substring(returnPrefix.length() + 8, returnPrefix.length() + 12);
                nextReturnSeq = Integer.parseInt(seqStr) + 1;
            }
        }
        String returnSeqStr = String.format("%04d", nextReturnSeq);
        String bloodReturnId = returnPrefix + dateStr + returnSeqStr;

        bloodReturnEntity.setBloodReturnId(bloodReturnId);
        bloodReturnEntity.setReason(bloodReturnEntity.getReason());
        bloodReturnEntity.setReview(BloodReturnVerifyStateEnum.IN_VERIFY.code());
        // 创建一个审核的实体
        OperateExamineEntity operateExamineEntity = new OperateExamineEntity();
        // 把公共属性拷贝进去，就是审核人姓名和Id
        BeanUtils.copyProperties(bloodReturnEntity,operateExamineEntity);
        operateExamineEntity.setOperateState(OperateStateEnum.WAIT.code());
        operateExamineEntity.setTradeType(TradeTypeEnum.BLOOD_RETURN.code());
        operateExamineEntity.setTradeId(bloodReturnId);
        boolean saveExamine = operateExamineService.save(operateExamineEntity);
        boolean saveBloodReturn = this.save(bloodReturnEntity);
        // 二者要同时满足
        return saveBloodReturn && saveExamine;
    }

    /**
     * 退血申请审核通过
     * @param
     * @return
     */
    @Override
    public Boolean approve(BloodReturnEntity bloodReturn) {
        //获取当前线程认证信息
        Authentication authentication= SecurityContextHolder.getContext().getAuthentication();
        String userName = null;
        String userId = null;
        if(authentication != null && authentication.isAuthenticated()){
            //获取当前用户id、name
            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
            //写入当前用户信息
            userName = loginUser.getUser().getUserName();
            userId = String.valueOf(loginUser.getUser().getUserId());
        }

        //
        LambdaQueryWrapper<BloodReturnEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BloodReturnEntity::getId,bloodReturn.getId());
        BloodReturnEntity bloodReturnEntity = bloodReturnDao.selectOne(queryWrapper);

        //将审核状态review改为通过”通过“
        LambdaUpdateWrapper<BloodReturnEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(BloodReturnEntity::getId,bloodReturnEntity.getId())
                .set(BloodReturnEntity::getReview,"PATIENT_BLOOD_RETURN_APPROVAL_GRANTED");

        //更新血液状态
        boolean bloodUpdate = bloodInformationService.updateBloodStateByBloodId(bloodReturnEntity.getBloodId(), "PATIENT_BLOOD_RETURN_APPROVAL_GRANTED");
        //更新库存表,更新字段bloodState,inStorgeTime,operatorId,operatorName
        LambdaUpdateWrapper<BloodInStorgeEntity> inStorgeUpdateWrapper = new LambdaUpdateWrapper<>();
        inStorgeUpdateWrapper.eq(BloodInStorgeEntity::getBloodId,bloodReturnEntity.getBloodId())
                .set(BloodInStorgeEntity::getBloodState,"PATIENT_BLOOD_RETURN_APPROVAL_GRANTED")
                .set(BloodInStorgeEntity::getInStorgeTime,new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()))
                .set(BloodInStorgeEntity::getOperatorId,userId)
                .set(BloodInStorgeEntity::getOperatorName,userName);

        boolean instorgeUpdate = bloodInStorgeService.update(inStorgeUpdateWrapper);


        return this.update(updateWrapper) && bloodUpdate && instorgeUpdate;
    }

    /**
     * 患者退血申请拒绝
     * @param bloodReturn
     * @return
     */
    @Override
    public Boolean reject(BloodReturnEntity bloodReturn) {
        //
        LambdaQueryWrapper<BloodReturnEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BloodReturnEntity::getId,bloodReturn.getId());
        BloodReturnEntity bloodReturnEntity = bloodReturnDao.selectOne(queryWrapper);

        //将审核状态改为拒绝”不通过“并写入审核意见
        LambdaUpdateWrapper<BloodReturnEntity> updateWrapper= new LambdaUpdateWrapper<>();
        updateWrapper.eq(BloodReturnEntity::getId,bloodReturnEntity.getId())
                .set(BloodReturnEntity::getReview,"PATIENT_BLOOD_RETURN_APPROVAL_DENIED")
                .set(BloodReturnEntity::getReviewOpinion,bloodReturn.getReviewOpinion());
        //血液状态更改
        boolean bloodUpdate = bloodInformationService.updateBloodStateByBloodId(bloodReturnEntity.getBloodId(), "PATIENT_BLOOD_RETURN_APPROVAL_DENIED");

        //更新库存表状态
        boolean storgeUpdate = bloodInStorgeService.updateInStorgeBloodStatebyBloodId(bloodReturnEntity.getBloodId(), "PATIENT_BLOOD_RETURN_APPROVAL_DENIED");

        return this.update(updateWrapper) && bloodUpdate && storgeUpdate;

    }

    @Override
    /**
     * 根据退血id进行查询退血数据
     */
    public BloodReturnEntity selectByReturnId(String bloodReturnId) {
        LambdaQueryWrapper<BloodReturnEntity> queryWrapper = new LambdaQueryWrapper<>();
        // 根据退血id查询出来一条数据
        queryWrapper.eq(Strings.isNotBlank(bloodReturnId),BloodReturnEntity::getBloodReturnId,bloodReturnId);
        return this.getOne(queryWrapper);
    }

    @Override
    public BloodReturnApplicationVo getReturnAlllicationInformation(String bloodId) {

        BloodReturnApplicationVo bloodReturnApplicationVo=new BloodReturnApplicationVo();

        LambdaQueryWrapper<BloodSendEntity> sendQueryWrapper = new LambdaQueryWrapper<>();
        sendQueryWrapper.eq(BloodSendEntity::getBloodId,bloodId);

        BloodSendEntity bloodSendEntity=bloodSendDao.selectOne(sendQueryWrapper);

        if (bloodSendEntity==null){
            return null;
        }

        bloodReturnApplicationVo.setPatientId(bloodSendEntity.getPatientId());
        //bloodReturnApplicationVo.setPatientName(bloodSendEntity.getPatientName());
        bloodReturnApplicationVo.setOperatorTime(bloodSendEntity.getOperatorTime());

        LambdaQueryWrapper<BloodMatchEntity> matchQueryWrapper = new LambdaQueryWrapper<>();
        matchQueryWrapper.eq(BloodMatchEntity::getBloodId,bloodId)
                .eq(BloodMatchEntity::getPatientId,bloodSendEntity.getPatientId());

        BloodMatchEntity bloodMatchEntity=bloodMatchDao.selectOne(matchQueryWrapper);

        bloodReturnApplicationVo.setMatchTime(bloodMatchEntity.getMatchTime());

        LambdaQueryWrapper<PatientInformationEntity> patientQueryWrapper = new LambdaQueryWrapper<>();
        patientQueryWrapper.eq(PatientInformationEntity::getPatientId,bloodSendEntity.getPatientId());

        PatientInformationEntity patientInformationEntity=patientInformationDao.selectOne(patientQueryWrapper);
        bloodReturnApplicationVo.setBedNumber(patientInformationEntity.getBedNumber());
        bloodReturnApplicationVo.setPatientName(patientInformationEntity.getPatientName());


        return bloodReturnApplicationVo;
    }
}